#include <dt-bindings/gpio/gpio.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/err.h>


#include <linux/workqueue.h>  //添加对应头文件


//用新的gpio接口
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>

// 13.新API函数，三级节点操作函数. 上面要注释掉，上面申请gpio了

/***
//  设备树配置
	led_ctrl:led_ctrl_gpio4 {
        //   status = "disabled";
		    status = "okay";
            compatible = "rk3568_led_ctrl";
			led1{
  			    	led-gpios =  <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>, <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;  //GPIO7_A2  
					pinctrl-names = "default";
            		pinctrl-0 = <&mygpio_ctrl>;
			};
			led2{
					led-gpios =  <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;  //GPIO7_A2	
			};
    };

   &pinctrl {
	 mygpio {
		 mygpio_ctrl: my-gpio-ctrl {
			 rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
		 };
	 };
   }



   学习函数:
   device_get_next_child_node
   fwnode_get_named_gpiod
   
 */


unsigned int count;
struct fwnode_handle *child_fw=NULL;
struct gpio_desc* leds[2]; 
int i=0;
int num=0;


// 13.新API函数，三级节点操作函数. 上面要注释掉，上面申请gpio了

// 第一章：驱动开发
static int led_ctrl_probe(struct platform_device *pdev) //compatible的属性和dts的compatible一致，就会调用probe函数
{


//&led_ctrl 子节点数量
    count = device_get_child_node_count(&pdev->dev);
//2 
	printk("count is %d\n ..  ",count);

/*
 参数1： 获取deivces
 参数2： 需要获取的子节点地址，
 如果传递NULL， 获取led_ctrl下第一个子节点地址，
 非NULL，改子节点下一个子节点地址
 *
 */
 //	child_fw = device_get_next_child_node(&pdev->dev,child_fw);

 
 //参数1 child_fw  就是led1 
 //参数2 属性名字 led-gpios
 //参数3： 
// redgpio-gpios  描述gpio索引值 0 ,1 
 // 比如 redgpio-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>, <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
 //参数4：   0  不进行初始化
 //参数5： 标签起一个名字，随便写
 // led[0]=fwnode_get_named_gpiod(child_fw,"led-gpios",0,0,"led1");

	for(i=0;i<count;i++){
		  // 获取下一个子设备节点
		child_fw = device_get_next_child_node(&pdev->dev,child_fw);
		if(child_fw){
  			leds[i]=fwnode_get_named_gpiod(child_fw,"led-gpios",0,0,"led");
			num=  desc_to_gpio(leds[i]);
		    printk("num is %d\n ..  ",num);
		}
	}



	return 0;
}


static int led_ctrl_remove(struct platform_device *pdv)
{
	return 0;
}


static struct of_device_id led_ctrl_match_table [] = {
	{.compatible = "rk3568_led_ctrl",}, //这里应该要跟dts的.compatible保持一致，我这里视频课程中没有写成一样，
        {},						//但他有个模糊匹配的功能，就是匹配相近的字段, 为了防止出错，大家最好写成跟dts一样的字段
	};

static struct platform_driver led_ctrl_driver = {
        .driver         = {
                .name = "rk3568_led_ctrl",
		.owner = THIS_MODULE, 
                .of_match_table = led_ctrl_match_table,
        },
        .probe          = led_ctrl_probe,
	.remove = led_ctrl_remove,
};

static int led_ctrl_init(void)
{
	printk("%s(), __%d__\n", __func__, __LINE__);

	platform_driver_register(&led_ctrl_driver); //注册platform平台总线驱动
	return 0;
}

static void led_ctrl_exit(void)
{
	printk("%s(), __%d__\n", __func__, __LINE__);

	
	platform_driver_unregister(&led_ctrl_driver); //注销驱动
}


module_init(led_ctrl_init); //模块加载函数, linux启动， insmod 驱动的时候 
module_exit(led_ctrl_exit); //模块卸载函数

MODULE_AUTHOR("caigong, 214241976@qq.com");   // 邮箱
MODULE_DESCRIPTION("Control Led Driver");    //作者
MODULE_LICENSE("GPL");       //驱动遵守的开源协议GPL
